{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# COBRA.jl - Tutorial"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial serves as a quick start guide as well as an interactive reference for more advanced users. Download the live notebook [here](https://github.com/opencobra/COBRA.jl/tree/master/docs/tutorial)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Installation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you do not already have the `COBRA.jl` package installed, you must first first follow the installation instructions [here](http://opencobra.github.io/COBRA.jl/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Please note that should you run this tutorial on an already configured system. Otherwise, the following lines will throw an error message."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before running any function of `COBRA.jl`, it is necessary to include the `COBRA.jl` module:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "using COBRA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can test your system by running:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "COBRA.checkSysConfig();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Beginner's Guide"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Should you not have any prior experience with Julia and/or Linux, **read carefully** the [Beginner's Guide](http://opencobra.github.io/COBRA.jl/stable/cobratutorial.html). If you however feel that you are set to proceed with this tutorial, please consider the Beginner's Guide as a go-to reference in case you are running into any issues. If you see unusual behavior, you may consider reading the [FAQ section](http://opencobra.github.io/COBRA.jl/stable/faq.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Quick help"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Do you feel lost or you don’t know the meaning of certain input parameters? Try typing a question mark at the Julia REPL followed by a keyword. For instance:\n",
    "\n",
    "```julia\n",
    "julia> ? distributedFBA\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Installation check and package testing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Make sure that you have a working installation of `MathProgBase.jl` and at least one of the supported solvers. You may find further information [here](http://mathprogbasejl.readthedocs.io/en/latest/). \n",
    "\n",
    "If you want to install other solvers such as `CPLEX`, `CLP`, `Gurobi`, or `Mosek`, you can find more information [here](https://github.com/JuliaOpt).\n",
    "\n",
    "You may, at any time, check the integrity of the `COBRA.jl` package by running:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```Julia\n",
    "julia> Pkg.test(\"COBRA\")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The code has been benchmarked against the `fastFVA` implementation [[3](#References-1)]. The modules and solvers are correctly installed when all tests pass without errors (warnings may appear)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Adding local workers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The connection functions are given in `connect.jl`, which, if a parallel version is desired, must be included separately:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "include(\"$(Pkg.dir(\"COBRA\"))/src/connect.jl\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You may add local workers as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# specify the total number of parallel workers\n",
    "nWorkers = 4 \n",
    "\n",
    "# create a parallel pool\n",
    "workersPool, nWorkers = createPool(nWorkers) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The IDs of the respective workers are given in `workersPool`, and the number of local workers is stored in `nWorkers`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In order to be able to use the `COBRA` module on all connected workers, you must invoke:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "@everywhere using COBRA;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define and change the COBRA solver\n",
    "\n",
    "Before the COBRA solver can be defined, the solver parameters and configuration must be loaded after having set the `solverName` (solver must be installed):\n",
    "\n",
    "- `:GLPKMathProgInterface`\n",
    "- `:CPLEX`\n",
    "- `:Clp`\n",
    "- `:Gurobi`\n",
    "- `:Mosek`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# specify the solver name\n",
    "solverName = :GLPKMathProgInterface\n",
    "\n",
    "# include the solver configuration file\n",
    "include(\"$(Pkg.dir(\"COBRA\"))/config/solverCfg.jl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# change the COBRA solver\n",
    "solver = changeCobraSolver(solverName, solParams)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "where `solParams` is an array with the definition of the solver parameters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load a COBRA model\n",
    "\n",
    "As a test and as an example, the *E.coli* core model may be loaded as:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# download the test model\n",
    "using Requests\n",
    "include(\"$(Pkg.dir(\"COBRA\"))/test/getTestModel.jl\")\n",
    "getTestModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load the stoichiometric matrix S from a MATLAB `structure` named model in the specified .mat file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = loadModel(\"ecoli_core_model.mat\", \"S\", \"model\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "where `S` is the name of the field of the stoichiometric matrix and `model` is the name of the model. Note the semicolon that suppresses the ouput of `model`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## Flux Balance Analysis (FBA)\n",
    "\n",
    "In order to run a flux balance analysis (FBA), `distributedFBA` can be invoked with only 1 reaction and without an extra condition:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# set the reaction list (only one reaction)\n",
    "rxnsList = 13\n",
    "\n",
    "# select the reaction optimization mode\n",
    "#  0: only minimization\n",
    "#  1: only maximization\n",
    "#  2: maximization and minimization\n",
    "rxnsOptMode = 1\n",
    "\n",
    "# launch the distributedFBA process with only 1 reaction on 1 worker\n",
    "minFlux, maxFlux  = distributedFBA(model, solver, nWorkers=1, rxnsList=rxnsList, rxnsOptMode=rxnsOptMode);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "where the reaction number `13` is solved. Note that the no extra conditions are added to the model (last function argument is `false`). The minimum flux and maximum flux can hence be listed as:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "maxFlux[rxnsList]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Flux Variability Analysis (FVA)\n",
    "\n",
    "In order to run a common flux variability analysis (FVA), `distributedFBA` can be invoked with all reactions as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# launch the distributedFBA process with all reactions\n",
    "minFlux, maxFlux, optSol, fbaSol, fvamin, fvamax = distributedFBA(model, solver, nWorkers=4, optPercentage=90.0, preFBA=true);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The optimal solution of the original FBA problem can be retrieved with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "optSol"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The corresponding solution vector `maxFlux` of the original FBA that is solved with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fbaSol"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The minimum and maximum fluxes of each reaction are in:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "maxFlux"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The flux vectors of all the reactions are stored in `fvamin` and `fvamax`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fvamin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "fvamax"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Distributed FBA of distinct reactions\n",
    "\n",
    "You may now input several reactions with various `rxnsOptMode` values to run specific optimization problems."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rxnsList = [1; 18; 10; 20:30; 90; 93; 95]\n",
    "rxnsOptMode = [0; 1; 2; 2+zeros(Int, length(20:30)); 2; 1; 0]\n",
    "\n",
    "# run only a few reactions with rxnsOptMode and rxnsList\n",
    "# distributedFBA(model, solver, nWorkers, optPercentage, objective, rxnsList, strategy, preFBA, rxnsOptMode)\n",
    "minFlux, maxFlux, optSol, fbaSol, fvamin, fvamax, statussolmin, statussolmax = distributedFBA(model, solver);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the reactions can be input as an unordered list."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Saving the variables"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can save the output of `distributedFBA` by using:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "saveDistributedFBA(\"results.mat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the results are saved in a `.mat` file that can be opened in MATLAB for further processing."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cleanup\n",
    "\n",
    "In order to cleanup the files generated during this tutorial, you can remove the files using:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "rm(\"ecoli_core_model.mat\")\n",
    "rm(\"results.mat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. [B. O. Palsson. Systems Biology: Constraint-based Reconstruction and Analysis. Cambridge University Press, NY, 2015.](http://www.cambridge.org/us/academic/subjects/life-sciences/genomics-bioinformatics-and-systems-biology/systems-biology-constraint-based-reconstruction-and-analysis?format=HB)\n",
    "2. [Schellenberger, J. et al. COBRA Toolbox 2.0. 05 2011.](https://github.com/opencobra/cobratoolbox)\n",
    "3. [Steinn, G. et al. Computationally efficient flux variability analysis. BMC Bioinformatics, 11(1):1–3, 2010.](https://bmcbioinformatics.biomedcentral.com/articles/10.1186/1471-2105-11-489)\n",
    "4. [Orth, J. et al. Reconstruction and use of microbial metabolic networks: the core escherichia coli metabolic model as an educational guide. EcoSal Plus, 2010.](http://gcrg.ucsd.edu/Downloads/EcoliCore)\n"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Julia 0.5.2",
   "language": "julia",
   "name": "julia-0.5"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "0.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
